package net.lh.contactsserver.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import javax.annotation.PostConstruct;

import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import net.lh.contactsserver.Config;
import net.lh.contactsserver.entity.Contact;
import net.lh.contactsserver.utils.ExcelHelper;

@Component
public class ContactService {
	
	@Autowired
	private Config config;
	
	@Value("${excel.reload-interval}")
	private int reloadInterval;
	
	private static Logger logger = LoggerFactory.getLogger(ContactService.class);

	/**
	 * 通讯录集合，key为姓名，value为明细
	 */
	private Map<String, Contact> contactMap = new HashMap<String, Contact>();
	
	private long lastExcelTime = 0;
	
	/**
	 * 构造函数
	 */
	@PostConstruct
	public void init() {
		load();
		
		// 最小时间间隔是1秒
		if (reloadInterval < 1) {
			reloadInterval = 1;
		}
		
		// 定时自动扫描Excel更新
		Timer t = new Timer();
        t.schedule(new TimerTask(){

			@Override
			public void run() {
				load();
			}}, reloadInterval*1000, reloadInterval*1000);
	}
	
	/**
	 * 读取Excel通讯录文件和头像
	 */
	public void load() {
		
		File excelFile = config.getExcelFilePath();
		
		if (!excelFile.exists() || !excelFile.isFile()) {
			logger.error("找不到通讯录Excel文件：{}", excelFile.getPath());
			return;
		}
		
		if (excelFile.lastModified() == lastExcelTime) {
			// Excel文件没有改变过，则只更新头像文件的时间戳（管理员在服务器上直接更新头像的场景）
			for (Contact contact : contactMap.values()) {				
				// 更新头像文件的id
				contact.setAvatarId(getAvatarId(contact.getName()));
			}
			return;
		}
		
		if (lastExcelTime > 0) {
			logger.info("发现Excel文件有更新，开始重新载入。");
		}
		
		List<Contact> list = readExcelFile(config.getExcelFilePath());
		logger.info("共读取{}条通讯录。", list.size());
		lastExcelTime = excelFile.lastModified();
		Map<String, Contact> map = new HashMap<String, Contact>();
		for (Contact contact : list) {
			map.put(contact.getName(), contact);
		}
		// 用新的通讯录替代旧的
		contactMap = map;
	}
	
	public Collection<Contact> list(String username, String password) {
		return contactMap.values();
	}
	
	//avatar/{avatar_id}
//	public File getAvatar(String avatarId) {
//		if (avatarId == null) {
//			return null;
//		}
//		
//		if (!avatarId.contains("_")) {
//			return null;
//		}
//		
//		final String userName = avatarId.substring(0, avatarId.indexOf("_"));
//		
//		// 查找该用户的所有图像文件
//		Collection<File> images = FileUtils.listFiles(new File(Config.AVATAR_DIR), 
//							new IOFileFilter() {
//
//								@Override
//								public boolean accept(File file) {
//									
//									if (userName.equals(FilenameUtils.getBaseName(file.getName()))
//										&& FilenameUtils.isExtension(file.getName(), new String[]{"jpg", "bmp", "png"})) {
//										return true;
//									} else {
//										return false;
//									}
//								}
//
//								@Override
//								public boolean accept(File dir, String name) {
//									return false;
//								}
//			
//							}, 
//							null);
//		
//		// 如果有多个头像文件（扩展名不同），则找修改时间最晚的
//		long lastTime = 0;
//		File lastImage = null;
//		for (File image : images) {
//			if (image.lastModified() > lastTime) {
//				lastImage = image;
//				lastTime = image.lastModified();
//			}
//		}
//		
//		return lastImage;
//	}
	
	/**
	 * 保存头像文件
	 * @param userName
	 * @param fileExtName
	 * @param is
	 * @throws IOException
	 */
	public void saveAvatarFile(String userName, String fileExtName, InputStream is) throws IOException {
		
		File file = new File(config.getAvatarStorePath(), userName + "." + fileExtName);
		FileUtils.forceMkdirParent(file);
		if (file.exists() && file.isFile()) {
			file.delete();
		}
		
		try {
			FileUtils.copyInputStreamToFile(is, file);
			updateAvatarId(userName, getAvatarId(userName));
		} catch (IOException e) {
			logger.error("文件保存失败!", e);
			throw e;
		}
	}

	/**
	 * 校验用户访问密码
	 * @param username
	 * @param password
	 * @return
	 */
	public boolean validateUser(String userName, String password) {
		return contactMap.containsKey(userName);
	}

	/**
	 * 删除某用户的头像jpg文件
	 * @param userName
	 */
	public void deleteAvatarFile(String userName) {
		File image = findAvatarFile(userName);
		if (image != null) {
			image.delete();
		}
		updateAvatarId(userName, "");
	}
	
	/**
	 * 查找某用户的头像文件（jpg）。如果找不到，返回null。
	 * @param userName
	 * @return 头像文件 或 null
	 */
	public File findAvatarFile(String userName) {
		File image = new File(config.getAvatarStorePath(), userName + ".jpg");
        if (image.exists() && image.isFile()) { 
        	return image;
        } else {
        	return null;
        }
	}
	
	/**
	 * 从Excel文件中获取通讯录列表。如果文件不存在
	 * @param importFile 通讯录Excel
	 * @return 通讯录列表
	 */
	public List<Contact> readExcelFile(File importFile) {
		List<Contact> contactList = new ArrayList<Contact>();
		
		if (importFile == null || !importFile.exists() || !importFile.isFile() || !importFile.canRead()) {
			logger.error("无法读取通讯录Excel文件！" );
			return contactList;
		}
		
		Workbook workbook ;
		InputStream is = null;
		try {
			is =  new FileInputStream(importFile);	
			if (importFile.getName().endsWith("xls") ) {
				workbook = new HSSFWorkbook(is);
			}else{
				workbook = new XSSFWorkbook(is);
			}

			Sheet sheet = workbook.getSheetAt(0);
			// 行遍历
			for (int j = 1; j <= sheet.getLastRowNum(); j++) {
				
				String name = ExcelHelper.getCellValue(sheet, j, 1).trim();
				if (name == null || name.isEmpty()) {
					continue;
				}
	
				Contact contact = new Contact();
				// 列遍历
				contact.setName(name);			
				contact.setCompany(ExcelHelper.getCellValue(sheet, j, 2).trim());
				contact.setDepartment(ExcelHelper.getCellValue(sheet, j, 3).trim());
				contact.setJobTitle(ExcelHelper.getCellValue(sheet, j, 4).trim());
				contact.setMobile1(ExcelHelper.getCellValue(sheet, j, 5).trim());
				contact.setPhone(ExcelHelper.getCellValue(sheet, j, 6).trim());
				contact.setComment(ExcelHelper.getCellValue(sheet, j, 7).trim());
				contact.setPassword(ExcelHelper.getCellValue(sheet, j, 8).trim());
				
				// 查找头像文件，如果有，则根据头像文件的时间戳设置头像ID
				contact.setAvatarId(getAvatarId(name));
				contactList.add(contact);
			}
		} catch (IOException e) {
			logger.error("读取通讯录Excel文件失败！", e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
				}
			}
		}

		return contactList;
	}

	/**
	 * 查找用户的头像文件，根据文件日期生成头像ID。
	 * @param username
	 * @return
	 */
	private String getAvatarId(String userName) {
		File image = findAvatarFile(userName);
		if (image != null) {
			return userName + "_" + image.lastModified();
		} else {
			return "";
		}
	}
	
	/**
	 * 设置内存中某用户的头像ID
	 * @param userName 用户名
	 * @param newID。 可以为null或""。
	 */
	private void updateAvatarId(String userName, String newID) {
		Contact contact = contactMap.get(userName);
		if (contact != null) {
			contact.setAvatarId(newID);
		}
	}
}
